﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DosciWordPlugin.Models;
using DosciWordPlugin.Common;
using Microsoft.Office.Interop.Word;

namespace DosciWordPlugin.Controls
{
    public partial class ReferencePanel : UserControl
    {
        private const string REFERENCE_ITEM_NAME = "referenceItem";
        private const int ORI_TOP = 5;

        public event Func<List<ReferenceModel>, bool> InsertCitationEvent;
        public event Action SetCitationStyleEvent;
        public event Action RefreshCitationStatusEvent;
        public event Action SearchCitationEvent;

        private bool _inMultiSelect = false;

        const int WM_KEYDOWN = 0x100;
        const int WM_KEYUP = 0x101;

        protected override bool ProcessKeyPreview(ref Message m)
        {
            if (m.Msg == WM_KEYDOWN)
            {
                int intWParam = m.WParam.ToInt32();
                if (intWParam == 17)
                {
                    _inMultiSelect = true;
                    return true;
                }
            }
            else if (m.Msg == WM_KEYUP)
            {
                int intWParam = m.WParam.ToInt32();
                if (intWParam == 17)
                {
                    _inMultiSelect = false;
                    return true;
                }
            }

            return base.ProcessKeyPreview(ref m);
        }

        public ReferencePanel()
        {
            InitializeComponent();
        }

        private List<ReferenceItem> _referenceList = new List<ReferenceItem>();
        public List<ReferenceItem> ReferenceList { get { return _referenceList; } }

        public void RefreshUseStatus(Document doc) 
        {
            try
            {
                List<string> nameList = new List<string>();
                foreach (Bookmark bookmark in doc.Bookmarks)
                {
                    nameList.Add(bookmark.Name);
                }
                ReferenceList.ForEach(r =>
                {
                    bool used = nameList.Contains(ReferenceModel.GetBookmarkNameFromID(r.ReferenceModel.ID));
                    r.SetUsed(used);
                });
                UpdateItemPosition();
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }

        public void AddReference(ReferenceModel referenceModel) 
        {
            try
            {
                if (referenceModel == null || string.IsNullOrEmpty(referenceModel.ID)) return;

                ReferenceItem referenceItem = new ReferenceItem(referenceModel);
                referenceItem.Name = REFERENCE_ITEM_NAME + referenceModel.ID;
                referenceItem.Top = _referenceList.Count * referenceItem.Height + ORI_TOP + this.splitContainer1.Panel1.AutoScrollPosition.Y;
                referenceItem.Anchor = AnchorStyles.Top|AnchorStyles.Left | AnchorStyles.Right;
                referenceItem.ClickEvent += this.ReferenceItem_Click;
                
                this.splitContainer1.Panel1.Controls.Add(referenceItem);
                _referenceList.Add(referenceItem);

                SetShowBorder();
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }

        public void RemoveReference(ReferenceModel referenceModel)
        {
            try
            {
                var item = _referenceList.Find(r => r.Name == REFERENCE_ITEM_NAME + referenceModel.ID);
                if (item != null)
                {
                    this.splitContainer1.Panel1.Controls.Remove(item);
                    _referenceList.Remove(item);

                    UpdateItemPosition();
                    SetShowBorder();
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }

        public void RemoveReferenceList(List<ReferenceModel> modelList)
        {
            try
            {
                if (modelList == null || modelList.Count <= 0) return;

                modelList.ForEach(referenceModel =>
                {
                    var item = _referenceList.Find(r => r.Name == REFERENCE_ITEM_NAME + referenceModel.ID);
                    if (item != null)
                    {
                        this.splitContainer1.Panel1.Controls.Remove(item);
                        _referenceList.Remove(item);
                    }
                });

                UpdateItemPosition();
                SetShowBorder();
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }
        
        public void UpdateItemPosition() 
        {
            this.splitContainer1.Panel1.AutoScrollPosition = new Point(0, 0);
            _referenceList = _referenceList.OrderBy(r => !r.ReferenceModel.IsUsed).ToList();
            //_referenceList.Sort(new Comparison<ReferenceItem>((a, b) => 
            //{
            //    if (a.ReferenceModel.IsUsed == b.ReferenceModel.IsUsed) return 0;

            //    return a.ReferenceModel.IsUsed ? -1 : 1;
            //}));
            for (int i = 0; i < _referenceList.Count; i++)
            {
                ReferenceItem referenceItem = _referenceList[i];
                referenceItem.Top = i * referenceItem.Height + ORI_TOP + this.splitContainer1.Panel1.AutoScrollPosition.Y;
            }
        }

        public void ClearRefrence() 
        {
            try
            {
                _referenceList.ForEach(r => this.splitContainer1.Panel1.Controls.Remove(r));
                _referenceList.Clear();
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }

        public void SetRefrenceList(List<ReferenceModel> referenceModelList) 
        {
            try
            {
                if (referenceModelList == null || referenceModelList.Count <= 0) return;

                ClearRefrence();
                referenceModelList.ForEach(r => AddReference(r));
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }

        public void ReferenceItem_Click(ReferenceItem referenceItem)
        {
            try
            {
                if (referenceItem.Selected)
                {
                    if (!_inMultiSelect)
                    {
                        // 单选
                        _referenceList.ForEach(r =>
                        {
                            if (r != referenceItem)
                            {
                                r.Selected = false;
                                r.BackColor = referenceItem.ColorUnselected;
                            }
                        });
                    }
                }

                var selectedList = _referenceList.FindAll(r => r.Selected);
                if (selectedList.Count != 1)
                    SetLabel(null);
                else
                    SetLabel(selectedList[0].ReferenceModel);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }

        private void SetLabel(ReferenceModel model = null)
        {
            if (model == null)
            {
                lbType.Text = "";
                lbAuthor.Text = "";
                lbYear.Text = "";
                lbTitle.Text = "";
                lbNumberOfPages.Text = "";
                lbKeywords.Text = "";
                txtDesc.Text = "";
            }
            else
            {
                lbType.Text = model.Type;
                lbAuthor.Text = model.Author;
                lbYear.Text = model.Year;
                lbTitle.Text = model.Title;
                lbNumberOfPages.Text = model.NumberOfPages;
                lbKeywords.Text = model.Keywords;
                txtDesc.Text = model.Digest;
            }

            label1.Visible = label5.Visible = label11.Visible = label9.Visible = label17.Visible = label15.Visible = label13.Visible = model != null;
        }

        private void SetShowBorder() 
        {
            for (int i = 0; i < _referenceList.Count; i++)
            {
                _referenceList[i].ShowBorderTop = true;
                _referenceList[i].ShowBorderBottom = i == _referenceList.Count - 1;
            }
        }

        private void picInsertLiterature_Click(object sender, EventArgs e)
        {
            try
            {
                var referenceList = _referenceList.FindAll(r => r.Selected);
                if (referenceList == null || referenceList.Count<=0)
                {
                    WinApp.MsgBoxError("请选择要插入的引文");
                    return;
                }
                if (InsertCitationEvent != null) 
                {
                    if (InsertCitationEvent(referenceList.Select(r=>r.ReferenceModel).ToList())) 
                        WinApp.MsgBoxInfo("插入成功！");
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }

        private void picCitationStyle_Click(object sender, EventArgs e)
        {
            if (SetCitationStyleEvent != null)
                SetCitationStyleEvent();
        }

        private void picRefresh_Click(object sender, EventArgs e)
        {
            if (RefreshCitationStatusEvent != null) RefreshCitationStatusEvent();
        }

        private void picBatchToLead_Click(object sender, EventArgs e)
        {
            try
            {
                if (SearchCitationEvent != null) SearchCitationEvent();
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
        }

        private void picRemove_Click(object sender, EventArgs e)
        {
            try
            {
                var referenceItemList = _referenceList.FindAll(r => r.Selected);
                if (referenceItemList == null || referenceItemList.Count <= 0)
                {
                    WinApp.MsgBoxError("请选择要从面板移除的引文");
                    return;
                }
                if (WinApp.MsgBoxOkCancel("确定要从面板移除选中的引文吗？") != DialogResult.OK) return;

                Dictionary<string, string> dicParam = new Dictionary<string, string>();
                dicParam.Add("id", string.Join(",", referenceItemList.Select(r => r.ReferenceModel.ID).ToArray()));
                HttpUtil.Post<string>(Constant.API_从远程面板删除, dicParam);

                RemoveReferenceList(referenceItemList.Select(r => r.ReferenceModel).ToList());
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                WinApp.MsgBoxError(ex.Message);
            }
        }

        private void ReferencePanel_Resize(object sender, EventArgs e)
        {
            _referenceList.ForEach(r => {
                r.Width = this.Width;
            });
        }
    }
}
